from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
# from solex3DFace import TFace
from fit_solex_three_face import create_ ,updataOSS
from face_merge import merge_multi_face
import base64
import numpy as np
import cv2,shutil
import orjson
import time
import os
from uploader import MinioUploader
import re

import multiprocessing as mp
# 创建 FastAPI 实例
app = FastAPI()
# tf_instance: TFace = None

# 创建全局变量来存储上传器
uploader = None
USE_MINIO = True  # 控制使用哪种上传方法的标志

def normalize_face_keys(data):
    """
    对输入的数据进行key标准化，将类似whiteFace_face_xxx或whiteFace_face-xxx的key
    标准化为基本形式：whiteFace_face, whiteLeft_left, whiteRight_right
    """
    normalized_data = []
    # 基本key模式
    base_patterns = {
        r"whiteFace_face[_-]?.*": "whiteFace_face",
        r"whiteRight_right[_-]?.*": "whiteRight_right",
        r"whiteLeft_left[_-]?.*": "whiteLeft_left"
    }
    
    for item in data:
        new_item = {}
        for key in item:
            normalized_key = key
            # 检查是否需要标准化
            for pattern, standard_key in base_patterns.items():
                if re.match(pattern, key):
                    normalized_key = standard_key
                    break
            # 使用标准化后的key
            new_item[normalized_key] = item[key]
        normalized_data.append(new_item)
    
    return normalized_data

# 应用启动时初始化上传器
@app.on_event("startup")
def startup_event():
    # 打印时间格式化
    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    global uploader
    if USE_MINIO:
        uploader = MinioUploader()
    # 如果需要其他上传方法，可以在这里添加else分支

# 定义请求体模型
class Item(BaseModel):
    path_name: str
    forward_img_link:str
    left_img_link:str
    right_img_link:str
# 健康检查接口
@app.get("/")
def read_root():
    return {"message": "Service is running", "status": "success"}

# 获取所有数据
@app.post("/rebuild3d")
async def rebuild3d(item: Item):
    print(item.path_name)
    print(item.forward_img_link)
    print(item.left_img_link)
    print(item.right_img_link)
    # 打印时间格式化
    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    img_link_list=[]
    img_link_list.append(item.forward_img_link)
    img_link_list.append(item.left_img_link)
    img_link_list.append(item.right_img_link)
    res={"message": "success", "errCode": 0,"time":"0ms","txt_link":""}

    # global tf_instance
    # tf_instance.clear()
    data=create_(img_link_list)
    file_front_path = "results/api_1/whiteFace_face_mesh.obj"
    file_left_path = "results/api_1/whiteLeft_left_mesh.obj"
    file_right_path = "results/api_1/whiteRight_right_mesh.obj"
    img_front_path = "results/api_1/whiteFace_face_uv.jpg"
    img_left_path = "results/api_1/whiteLeft_left_uv.jpg"
    img_right_path = "results/api_1/whiteRight_right_uv.jpg"
    save_dir = "results/api_2"

    data = normalize_face_keys(data)
    with open(os.path.join(save_dir,'output.json'), 'wb') as f:  # 注意 'wb' 二进制模式
        f.write(orjson.dumps(data, option=orjson.OPT_INDENT_2))
    print('WWWW:', data)
    start_time = time.time()
    merge_multi_face(file_front_path, file_left_path, file_right_path, img_front_path, img_left_path, img_right_path,
                     save_dir)

    shutil.make_archive(save_dir, 'zip', save_dir)
    local_zip_path=save_dir+".zip"

    print("all merge time:{}".format(time.time() - start_time))

    #上传oss：save_dir，path_name
    if USE_MINIO:
        # 使用Minio上传
        status, upload_zip_path = uploader.upload_file(local_zip_path, item.path_name)
    else:
        # 使用原来的上传方法
        status, upload_zip_path = updataOSS(local_zip_path, item.path_name)
    
    if status == 200:
        res["errCode"] = 0
        res["txt_link"] = upload_zip_path
    res["time"]=str(int(time.time()-start_time))+"ms"
    print(res)
    return res

@app.post("/rebuildDepth")
async def rebuildDepth(item: Item):
    print(item.path_name)
    print(item.forward_img_link)
    print(item.left_img_link)
    print(item.right_img_link)
    # 打印时间格式化
    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
    img_link_list=[]
    img_link_list.append(item.forward_img_link)
    img_link_list.append(item.left_img_link)
    img_link_list.append(item.right_img_link)
    res={"message": "success", "errCode": 0,"time":"0ms","txt_link":""}
    global tf_instance
    tf_instance.clear()
    startTim=time.time()*1000
    ossLink = item.path_name + "/front.jpg"
    tf_instance.rebuildDepth(item.forward_img_link,ossLink)

    ossLink = item.path_name + "/left.jpg"
    tf_instance.rebuildDepth(item.left_img_link,ossLink)

    ossLink = item.path_name + "/right.jpg"
    tf_instance.rebuildDepth(item.right_img_link,ossLink)

    res["time"]=str(int(time.time()*1000-startTim))+"ms"
    print(res)
    return res

if __name__ == "__main__":
    mp.set_start_method('spawn', force=True)  # 加force=True，确保一定是spawn，不受第一次影响
    # 不需要在这里初始化uploader，因为已经在startup_event中完成
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=9687)
